home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-10-19 | 59.6 KB | 1,498 lines |
- Chapter 3
- - continued -
- - Part 3 of 3 parts -
- of the
- Turbo Pascal Reference
-
- The Turbo Pascal Language
-
-
- This chapter is part of the Turbo Pascal Reference electronic freeware book (C)
- Copyright 1992 by Ed Mitchell. This freeware book contains supplementary
- material to Borland Pascal Developer's Guide, published by Que Corporation,
- 1992. However, Que Corporation has no affiliation with nor responsibility for
- the content of this free book. Please see Chapter 1 of the Turbo Pascal
- Reference for important information about your right to distribute and use this
- material freely. If you find this material of use, I would appreciate your
- purchase of one my books, such as the Borland Pascal Developer's Guide or
- Secrets of the Borland C++ Masters, Sams Books, 1992. Thank you.
-
- Functions
- Syntax:
-
- function <identifier> <parameter list> : <data type>
-
- Examples:
-
- function Minimum ( A, B : Integer ) : Integer;
- { Returns the value of the smaller number A, or B }
- begin
- if A < B then
- Minimum := A
- else { if B < A or B = A then }
- Minimum := B;
- end;
-
- { Example of a function returning a String value }
- function LowerCase (S : String ) : String;
- { Convert string S to lower case, returning the result }
-
- var
- I : Integer;
- begin
- for I := 1 to length(S) do
- if ((S[I]>='A') and (S[I]<='Z')) then
- S[I] := Chr( Ord( S[I] ) + 32 );
- LowerCase := S;
- end; { LowerCase }
-
- Description:
- A function is similar to a procedure, except that a function is called
- from within an expression and it returns a value that is then used in
- evaluating the overall expression. Functions can have both value and variable
- parameters, and may be declared as near, far, forward, and external, or may be
- implemented entirely in assembly language. Functions may not, however, be
- declared as interrupt functions.
-
-
- Calling a function
- The function is called by appearing within an expression, such as,
-
- I := Min ( X1, X2 ) + 1;
-
-
- Assigning a value to a function identifier
- The function's block definition must include a statement that assigns a
- value to the function's identifier. This is how a function gets a value that
- it can return to the caller. If you omit this assignment statement, or the
- assignment statement does not get executed as a result of conditional
- statements in the function's code, then the function returns an undefined or
- potentially random value. If during the course of debugging a program you find
- your functions returning erratic values, be certain that the function
- identifier is correctly assigned a value.
- Examples of assigning values to function identifiers appear above in the
- Min and LowerCase functions.
-
-
- Acceptable Function Return Values
- The data type that a function returns can be any of the following:
-
- Any ordinal value, including Boolean, Byte, Char, Smallint, Integer,
- Word, Longint, and enumarated data types and user defined sub range
- types.
-
- Real, Single, Double, Extended and Comp data types,
-
- Pointer values
-
- Strings.
-
-
- Functions may not return records or sets, although they may return pointers to
- records or sets.
-
-
- Recursive functions
- Functions may call themselves. Such a function is called a recursive
- function. A popular and simple example of a recursive function is a function
- that computes the factorial of a number. The factorial of a number n, is n *
- (n-1) * (n-2) ... until n reaches 1. For example, the factorial of 5, is 5 * 4
- * 3 * 2 * 1, which equals 120. An illustration of how this might be solved
- recursively is shown in listing 3.10. (Actually, its not necessary to use a
- recursive function to compute a factorial; this method is used here for
- illustration only.)
-
- Listing 3.10. An example of a recursive function.
- 1 program DemoRecursion; {DEMORECU.PAS}
- 2
- 3 function Factorial ( n : real ) : real;
- 4 begin
- 5 if n = 1 then
- 6 Factorial := 1
- 7 else
- 8 Factorial := N * Factorial ( N - 1.0 );
- 9 end;
- 10
- 11 var
- 12 X : Real;
- 13
- 14 begin
- 15 Write('Enter a number: ');
- 16 Readln( X );
- 17 Writeln;
- 18 Writeln('Factorial of ',X,' = ', Factorial ( X ) );
- 19 Writeln;
- 20 Write('Press Enter to finish.');
- 21 Readln;
- 22 end.
- 23
-
- Important note: The effect of short-circuit evaluation on functions
- By default, Turbo Pascal generates short-circuit evaluation code, so it is
- possible that a function may not be called within a particular expression. For
- example, consider a function defined as:
-
- function ValueInRange ( X1 : Integer ) : Boolean;
- begin
- ...
- if X1 > 0 then
- ValueInRange := True
- else
- ValueInRange := False;
- if X1 < LowestCoordinate then
- LowestCoordinate := X1;
- end;
-
- In this function, a global variable LowestCoordinate may have its value changed
- during the course of execution. If this function is called in an expression
- such as,
-
- if (X1<>X2) and ValueInRange(X1) then ...
-
- In normal short-circuit evaluation, if X1 is not equal to X2, then the
- remainder of the expression will not be evaluated. If your code depends upon
- the value of LowestCoordinate being set as a side effect of the ValueInRange
- function call, this may result in an error. In general, it is best to avoid
- side-effects within functions and procedures, but if you must make use of
- side-effect such as this, you should disable short-circuit evaluation to force
- the entire expression to be fully evaluated. See the section "Compiler
- Directives" for more information on using the {$B+} option to enable full
- expression evaluation.
-
-
- Procedures and Functions as Parameters
- A procedure or function may itself be passed to another procedure or
- function as a parameter value. To pass a procedure or function as a parameter
- requires that a type declaration define a procedure type that matches the
- appropriate procedure or function header. This type becomes the parameter type
- used in the procedure parameter list. Listng 3.11 demonstrates the use of a
- procedure parameter.
- Note that the type declaration describes the procedure or function that is
- called, and does not include the actual procedure or function identifier.
-
- Listing 3.11. Using a procedure type as a procedure parameter.
- 1 Program ProcParameter;{PROCPARM.PAS}
- 2 { Demonstrates using a procedure type as a procedure
- parameter }
- 3
- 4 type
- 5 FormatProc = procedure ( X : Integer );
- 6
- 7
- 8 const
- 9 MaxListSize = 15;
- 10 Values: array[1..MaxListSize] of Integer =
- 11 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
- 12
- 13
- 14
- 15 function Hexadecimal ( X: Word ) : String;
- 16 var
- 17 HiByte, LoByte : Word;
- 18
- 19 function HexConvert( B : Byte ) : String;
- 20 const
- 21 HexTable : Array[0..15] of Char =
- 22 ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- 23 'A', 'B', 'C', 'D', 'E', 'F');
- 24 begin
- 25 HexConvert := HexTable[B div 16] + HexTable[B and 15];
- 26 end;
- 27
- 28 begin
- 29 HiByte := X Div 256;
- 30 LoByte := X and 255;
- 31 Hexadecimal := HexConvert( HiByte ) + HexConvert(LoByte);
- 32 end;
- 33
- 34
- 35
- 36 procedure PrintInteger( X : Integer ); far;
- 37 begin
- 38
- 39 Writeln( X : 5 );
- 40
- 41 end;
- 42
- 43
- 44
- 45 procedure PrintHex( X : Integer ); far;
- 46 begin
- 47
- 48 Writeln ( Hexadecimal ( X ) );
- 49
- 50
- 51 end;
- 52
- 53
- 54 procedure PrintPercent( X : Integer ); far;
- 55 begin
- 56
- 57 Writeln( X, '%');
- 58
- 59 end;
- 60
- 61
- 62 procedure Traverse ( Proc : FormatProc );
- 63 var
- 64 I : Integer;
- 65 begin
- 66 for I := 1 to MaxListSize do
- 67 Proc( Values[I] );
- 68 end;
- 69
- 70
- 71 begin
- 72 Traverse ( PrintInteger );
- 73 Traverse ( PrintHex );
- 74 Traverse ( PrintPercent );
- 75
- 76 readln;
- 77
- 78 end.
-
-
- Conditional Compilation
- While not specifically a part of the Pascal programming language, Turbo
- Pascal provides special compiler directives to create different executable
- programs from a single source. These features are called conditional
- compilation directives. The basic statements are,
-
- {$IFxxxx} <Pascal statements> {$ENDIF}
-
- and
-
- {$IFxxxx} <Pascal statements> {$ELSE} <Pascal statements>
- {$ENDIF}
-
- where the {$IFxxxx} may be one of the following conditional tests,
-
- {$IFDEF symbol}: If symbol is defined, then compile the statements
- between the {$IFDEF} and the {$ENDIF} or {$ELSE}.
-
- {$IFNDEF symbol}: If symbol is not defined, then compile the
- statements between the {$IFNDEF} and the {$ENDIF} or {$ELSE}.
-
- {$IFOPT switch}: Tests the state of compiler directive switches (such
- as $R+ or $I-, for instance). For example, {$IFOPT I+} compiles the
- following Pascal statements if the $I options is currently set, while
- {$IFOPT I-} compiles the following statements if the $I options is not
- set.
-
- These statements may be embedded into Pascal source code like any other
- program comment. Symbols used in conditional compilation statements are
- created with the {$DEFINE symbol} directive, and eliminated or undefined with
- the {$UNDEF symbol} directive.
- A frequent use of conditional compilation is to embed debugging code into
- a program during development. By changing a single option, all of the debug
- code can be eliminated from the final compilation, but switched back on if bugs
- are detected or new program features are added later. Listing 3.12 illustrates
- the use of the conditional compiler directives in a section of code.
-
- Listing 3.12. This program section shows how conditional compilation might be
- used to add debug statements into a program.
- 1 {$DEFINE DEBUGGING} {DEBUG.PAS}
- 2 {$IFDEF DEBUGGING}
- 3 procedure DebugTrace( S : String; X : Integer );
- 4 begin
- 5 Writeln( DebugFile, S,', ', X );
- 6 end;
- 7 {$ENDIF}
- 8
- 9 {---------------------------------------------------------}
- 10 function UpperCase ( S : String ) : String;
- 11 var
- 12 I : Integer;
- 13 begin
- 14 {$IFDEF DEBUGGING}
- 15 DebugTrace('UpperCase', 0 );
- 16 {$ENDIF}
- 17 for I := 1 to Length( S ) do
- 18 S[I] := UpCase ( S[I] );
- 19 UpperCase := S;
- 20 end; { UpperCase }
- 21 {------------------------------------------------------------}
- 22 function HeapFunc ( Size : Word ) : integer;
- 23 begin
- 24 {$IFDEF DEBUGGING}
- 25 DebugTrace('HeapFunc', 0 );
- 26 {$ENDIF}
- 27
- 28 HeapFunc := 1;
- 29 end;
- 30
- 31 {-----------------------------------------------------------}
- 32 function LowerCase (S : String ) : String;
- 33 Var
- 34 I : Integer;
- 35 begin
- 36 {$IFDEF DEBUGGING}
- 37 DebugTrace('LowerCase', 0 );
- 38 {$ENDIF}
- 39
- 40 for I := 1 to length(s) do
- 41 if ((S[I]>='A') and (S[I]<='Z')) then
- 42 S[I] := Chr( Ord( S[I] ) + 32 );
- 43 LowerCase := S;
- 44 end;
- 45
- 46 {------------------------------------------------------------}
- 47 Function Max ( A, B : Integer ) : Integer;
- 48 Begin
- 49 {$IFDEF DEBUGGING}
- 50 DebugTrace('Max', 0 );
- 51 {$ENDIF}
- 52
- 53 IF A>B THEN Max := A Else Max := B;
- 54 End; {Max}
- 55
-
- Important Note: Conditional Symbols
- The symbols defined by {$DEFINE} must follow the same rules as those
- applied to normal Pascal language identifiers. However, symbols defined by
- {$DEFINE} are completely unrelated to identifiers declared within Pascal
- programs. For example, it is permissible to have,
-
- {$DEFINE Debug}
- var
- Debug : Boolean;
-
- because these identifiers have no relation to one another. Similarly, if you
- wrote,
-
- {$DEFINE Options}
- if Options then ....
-
- you would receive an error because the symbol Options used in the if-then
- statement has not been declared (at least as a Pascal identifier).
- In addition to the {$DEFINE} directive, symbol may also be defined with
- the /D command line option (See Chapter 10, "Turbo Pascal Standalone Programs"
- in the Borland Pascal Developer's Guide) or the Conditional Defines option of
- the IDE (see chapter 2 of the Turbo Pascal Reference).
-
-
- Built-in Conditional Compilation Symbols
- Turbo Pascal automatically defines the following 4 conditional compilation
- symbols:
-
- VER60: Turbo Pascal automatically defines this symbol, meaning that
- this is version 6.0 of the Turbo Pascal compiler.
-
- VER70: Turbo Pascal defines this symbol when you are compiling under
- version 7.0 of the Turbo Pascal compiler.
-
- MSDOS: Defined for all MS-DOS versions of the Turbo Pascal.
-
- CPU86: Defined for all versions of Turbo Pascal running on 80x86
- microprocessors.
-
- CPU87: If, at compile time, the compiler detects an 80x87 math
- coprocessor, this symbol is automatically defined. When used in
- conjunction with {$N}, this symbol can be used to set the floating-point
- libraries for use with or without the 80x87 coprocessor. Example:
- {$IFDEF CPU87} {$N+} {$ELSE} {$N-} {$ENDIF}
-
-
- Compiler Directives
- Compiler directives are special program comments that select compiler
- options. Two types of compiler directives are provided (in addition to the
- conditional compiler options just described):
-
- Switch directives: These are written in the form {$I+} or {$I-}, where
- $I specifies a particular option, and a + symbol switches the option on,
- and a minus - symbol switches the option off.
-
- Parameter directives: Parameters specify a value to the option, such
- as, {$I filename} to include another file during compilation.
-
- Compiler options may be set by embedding compiler directives into the source
- text, or may be set globally using the IDE's Options menu, Compiler selection.
- (See Chapter 2, in the section titled "Options Menu/Compiler)". Many of the
- options may also be specified as command line options to the command line
- version of the compiler (See Chapter 10 in the Borland Pascal Developer's
- Guide).
- Table 3.3 describes the embedded compiler directive options.
-
-
- Table 3.3. The $ compiler directives.
-
- Word align data: $A, default $A+
- Normally, the compiler generates byte aligned data assignments.
- Setting this option forces the compiler to generate word aligned
- assignments, so that if one value ends on an odd byte, the compiler
- will skip a byte to insure that the next assignment is made to an
- even byte position. The 80x86 CPUs, including the 8086, operate
- slightly faster when fetching word-aligned data than when fetching
- byte aligned data.
-
- Complete Boolean evaluation: $B, default $B-
- The Turbo Pascal compiler normally performs short-circuited boolean
- expression evaluation. This means that as the expression is
- evaluated at run time, as soon as the result is definitely known, the
- remainder of the expression will be ignored. This is particularly
- useful in testing an index value before using it in an array
- subscript, in for example,
- if Index < 10 and (X[Index]=9) then...
- If Index is 10 or greater, the program will not execute the array
- subscript. However, by enabling this compiler option, $B+, you can
- force the program to always fully evaluate the expression. This
- might be used when calling a function within an expression, and your
- program must use an intended side affect of the function call.
-
- Debug information: $D, default $D+
- If you are going to use either the built-in or the standalone
- debuggers, set this option on so that the compiler will generate
- internal line number tables to assist in matching generated code to
- program source statements. You can selectively disable debug
- information on a per unit basis; such units cannot have their
- procedures or functions traced into.
-
- Emulation: $E, default $E+
- When this option is set, the compiler will link in routines that
- automatically detect the prescence or abscence of the floating point
- processors. If the math processor is installed, then it will be
- used; if the math processor is not installed, the routines that
- simulate the processor are called instead. To generate code for all
- types of machines, regardless of whether or not they have a floating
- point chip, select both the 8087/80287 and the Emulation options. If
- you know that the target machine definitely has a coprocessor, then
- disable this option but enable the 8087/80287 option. See Table 3.1
- and A Note on the Use of Floating Point Values earlier in this
- chapter for additional information concerning Pascal floating point
- data types and use of the math coprocessor and emulation libraries.
-
- Force far calls: $F, default $F-
- Normally, the compiler generates near calls for all procedure and
- functions in the current file, and far calls for all procedures or
- functions appearing in the interface portion of a unit. You can
- force far call generation by selecting this option. Also see the
- section @ and Procedures and Functions, for examples using the far
- option for passing procedures and functions as parameters to
- procedures.
-
- 286 instructions: $G, default $G-
- When set, the compiler generates code using the additional
- instructions available in the 80286 instruction set. Programs
- created with this option will not run on 8088 or 8086 processors.
-
- I/O checking: $I, default $I+
- The default setting is to have the compiler check for input/output
- errors on all input/output operations, such as reading or writing to
- a file. However, usually you will want to have your own checks for
- such errors so you will want to disable this option. Usethe $I-
- compiler directive to locally disable I/O checking. You can then
- check the value of the IOResult function to determine if an error
- occurred. See Checking for File-related Errors, later in this
- chapter.
-
- Include File parameter directive: $I filename
- This form of the $I compiler directive causes the specified filename
- to be incorporated directly into the Pascal source text at the
- location of the directive. Its operation is as if the included file
- has been typed at this location in the original source file. The $I
- is a convenient way of breaking large source files into smaller, more
- manageable pieces. Included files may themselves include other
- files, up to a maximum nesting depth of 15 files. The only
- restriction is that all statements between a begin - end pair must
- appear in the same source file. For example,
- Program Demo;
- var
- ...
- {$I IOPROCS.PAS}
- {$I ERRCODE.PAS}
- begin { Demo }
- ...
- end; { Demo }
-
- Local symbols: $L, default $L+
- When set, the compiler builds a table of all local variables and
- constant identifiers for use during debugging session. If {$D-} is in
- effect, disabling the generation of debug information, then {$L+} is
- ignored. See also the $D option, above.
-
- Link object file parameter directive: $L filename
- When using external assembly language routines, the $L parameter
- directive tells the compiler which .OBJ file contains the externally
- defined routine.
-
- Memory allocation parameter directive: $M stacksize, heapmin, heapmax,
- Default $M 16384, 0, 655360
- The $M parameter directives specifies, for a Program module, how much
- memory to allocate to the program stack, and the minimum and maximum
- size permitted for the heap memory allocation. The default values
- specify a stack size of 16k bytes, and a maxium heap allocation up to
- 640k bytes. During program initialization, the heap memory is
- allocated from whatever is left over after loading the program code
- and setting aside space for global variables and the stack. As a
- result, the actual heap allocation may be less than the maximum value
- specified in this directive.
- The stacks size may be set to any value from 1,204 to 65,520 bytes.
- The heap values may be set anywhere from 0 to 655,360 bytes.
-
- 8087/80287: $N, default $N-
- When set, this results in the compiler generating code for the 8087
- or 80x87 math coprocessor chip. This option is often used in
- conjunction with the Emulation mode option (see above). Also see See
- Table 3.1 and A Note on Floating Point Values earlier in this chapter
- for additional information concerning Pascal floating point data
- types and use of the math coprocessor and emulation libraries.
-
- Overlays allowed: $O, default $O-
- You must set this option for all units that will subsequently be
- overlaid. Its also okay to set this option for units that are not
- overlaid as it merely adds some additional run time checks to the
- generated code. Chapter 3, "Overlays" in the Borland Pascal
- Developer's Guide describes the creation and use of overlay programs.
-
- Overlay unit name parameter directive: $O unitname
- When a Program module will use overlay units, immediately after the
- uses statement, the program must specify which units should be placed
- in a separate .OVR overlay file instead of the main .EXE program
- executable file. All such overlay units must be compiled with the
- $O+ option. See Chapter 2, "Units and Dynamic Link Libraires" for
- information on creating and using program units, and chapter 3,
- "Overlays" for information on using overlays, both in the Borland
- Pascal Developer's Guide.
-
- Range checking: $R, default $R-
- Range checking can be performed on all array and string subscript
- values. If the index is out of range, then a run time error occurs
- and the program halts. Set this option to enable range checking, and
- disable this option to turn off range checking. Programs may run
- noticeably faster with range checking turned off, and will require
- somewhat less code.
-
- Stack checking: $S, default $S+
- When this option is set, the compiler generates extra code for every
- procedure and function call to insure that adequate memory remains in
- the stack area. If the call would cause the program to run out of
- memory, the program is halted with a run-time error.
-
- Strict var-strings: $V, default $V+
- Most Pascal compilers will not let you pass a string variable as a
- var parameter unless both var parameters are exactly the same type
- and length. For example, you normally cannot pass a STRING[80] typed
- variable to a procedure having a var parameter defined (via a type
- declaration) as STRING[128]. However, by selecting the $V- option,
- Turbo Pascal allow you to pass mismatched string types as procedure
- parameters.
-
- Extended syntax: $X, default $X-
- When $X+ is in effect, Turbo Pascal lets you call a function just
- like it was a procedure. In effect, the result of the function will
- be ignored and thrown away.
- This feature does not apply to any System unit functions.
-
-
- Disk File Operations
- Turbo Pascal provides disk file access through file declarations, standard
- library procedures, functions and system variables. Turbo Pascal programs can
- read and write text files (containing text information), as well as reading and
- writing random access disk files containing complex data records.
- This section describes basic file operations, and then presents example
- code for reading and writing text files, reading and writing sequential and
- random access data files, and an example using the high speed BlockRead and
- BlockWrite file functions.
-
-
- Defining a File Identifier
- Text files are accessed through a special data type called Text, such that
- a file identifier is declared as,
-
- var
- TextFileID : Text;
-
- Data files (those containing data other than text files) are accessed via a
- File identifier declared using the syntax,
-
- var
- FileId : File of <type>;
-
- where <type> is any type identifier, including built in data types, records and
- user defined types. Some examples:
-
- type
- TPersonInfo = record
- Name : String[20];
- Age : Integer;
- end;
- var
- DataFile1 : File of Real;
- DataFile2 : File of Integer;
- DataFile3 : File of TPersonInfo;
-
-
- Opening a File
- A filename is associated with a file identifier by calling the Assign
- procedure, like this:
-
- Assign ( DataFile1, 'QTR-DATA.DAT' );
-
- which assigns the filename 'QTR-DATA.DAT' to file identifier DataFile1. This,
- however, does not actually open the file.
- To open an existing file, use the Reset procedure (or the Append
- procedure, summarized later):
-
- Reset ( DataFile1 );
-
- To create a new file and open it so that data can be written to the file,
- write:
-
- Rewrite ( DataFile1 );
-
-
- Writing and Reading File Data
- Data is output to a data file using the standard Write procedures and
- specifying the file identifier as the first parameter. Example:
-
- Write ( DataFile1, 3.14159 );
-
- Each time data is output to the file, an internal file pointer is advanced
- forward into the file. When a file is first opened, the file pointer is
- located at the beginning of the file. Once a record is written to the file,
- the file pointer advances to just beyond that record, so that it points to the
- next position in the file.
- If a previously created file was opened using Reset, data may be read by
- using Read, specifying the file identifier as the first identifier, followed by
- a data variable to store the results. Example:
-
- Read ( DataFile1, X );
-
-
- Checking for File-related Errors
- By default, if a file operation error is detected, such as unable to open
- a file, the program halts with a run-time error. However, your program can
- disable automatic file error detection and process file errors directly by
- checking the value returned by the IOResult function.
- To test for file errors, you must set the {$I-} option to disable
- automatic I/O (input/output) result checking. Then, perform the desired
- option. Example:
-
- {$I-}
- Reset( DataFile1 );
- {$I+}
- ErrorCode := IOResult;
- if ErrorCode <> 0 then
- begin
- Writeln('Problem opening the file');
- ...
- end;
-
- While you can test the value of IOResult directly, you will probably want
- to copy its integer result to a variable, as shown in the code fragment above.
- This is because IOResult returns the result code of the previous I/O operation,
- and then resets the internal error code to 0. Consequently, if you test
- IOResult in a conditional statement, and then attempt to access the error code
- again to display an error message or perform other processing, IOResult will
- now be zero.
-
-
- Text Files
- Listing 3.12 demonstrates reading and writing text files. This simple
- program prompts for a filename to read from, and the name of file to copy to.
- It opens the input file, InFile using the Reset procedure. The output file,
- OutFile is opened using Rewrite to create the new file. However, to insure
- that an existing file is not inadvertently overwritten, the program first
- attempts to open the file using the Reset procedure. If the IOResult is zero,
- this means that the file already exists, so the program prompts to see if you
- really wish to overwrite the existing file. Then the file is opened using the
- Rewrite procedure.
- Finally, a while loop reads each line from InFile, and writes it to
- OutFile, displaying a dot or period '.' on the screen for each line that is
- processed, providing user feedback that the program is doing something. (Its a
- good idea to present some type of feedback whenever your program performs time
- consuming tasks. If nothing happens for too long, the user might suspect the
- program has crashed, or perhaps is reformatting the hard disk, neither of which
- makes for user friendly software.)
- The while loop calls the function Eof, which returns True when the end of
- the input file has been reached. If the program did not call Eof, it would
- eventually attempt to read beyond the end of the file, resulting in a run-time
- error. While not shown in this example, you could disable I/O result checking
- using {$I-} and check the IOResult function after each Read and Write.
- You may wish to modify this program to perform various types of data
- manipulation. For instance, you can easily alter this program to create a
- program that puts line numbers on Pascal source statements. Add a TotalLines
- line counter variable, set to zero, and then increment by 1 for each line read
- from the input file. Add TotalLines to the Writeln output statement, like
- this:
-
- Writeln( OutFile, TotalLines:4, ': ', DataLine );
- To send output to the printer, instead of another disk file, specify LPT1: (or
- other appropriate DOS printer device) for the output file name.
-
- Listing 3.12. An example program showing how process text files.
- 1 program TextFiles; {TEXTFILE.PAS}
- 2 { Demonstrates copying a text file to another file }
- 3
- 4 var
- 5 DataLine : String;
- 6 Error : Integer;
- 7 InFileName : String[80];
- 8 InFile : Text;
- 9 Line : Integer;
- 10 OutFileName : String[80];
- 11 OutFile : Text;
- 12 TotalLines : Word;
- 13 Response : String[80];
- 14
- 15
- 16 begin
- 17
- 18 { Get name of input file and open the file }
- 19 Repeat
- 20
- 21 Write('Enter the name of the file to read (CR=done): ');
- 22 Readln( InFileName );
- 23 if Length( InFileName ) > 0 then
- 24 begin
- 25 Assign( InFile, InFileName );
- 26 {$I-}
- 27 Reset( InFile );
- 28 {$I+}
- 29 Error := IoResult;
- 30 if Error <> 0 then
- 31 writeln('Unable to open ',InfileName,'.');
- 32 end; { if begin }
- 33
- 34 Until (Error = 0) or (Length( InFileName ) = 0);
- 35
- 36
- 37 { Get name of output file and open the file }
- 38 If Length( InFileName ) > 0 then
- 39 begin
- 40
- 41 repeat
- 42 repeat
- 43 Error := 0;
- 44 Write('Enter the name of the file to COPY TO (CR=done): ');
- 45 Readln( OutFileName );
- 46 if Length( OutFileName ) > 0 then
- 47 begin
- 48 Assign( OutFile, OutFileName );
- 49 {$I-}
- 50 Reset( OutFile );
- 51 {$I+}
- 52 Error := IoResult;
- 53 if Error = 0 then
- 54 begin
- 55 Close ( OutFile );
- 56 Write(OutFileName,' already exists. Overwrite (Y/Cr=No)? ');
- 57 Readln( Response );
- 58 if (Response = 'Y') or (Response = 'y') then
- 59 Error := 1; { Allow exit from the filename query loop }
- 60 end; { if begin }
- 61 end; { if begin }
- 62 until (Error <> 0) or (Length( OutFileName ) = 0);
- 63
- 64 if Error <> 0 then
- 65 begin
- 66 {$I-}
- 67 Rewrite( OutFile );
- 68 {$I+}
- 69
- 70 Error := IoResult;
- 71 if Error <> 0 then
- 72 Writeln('Problem creating ',OutFileName,'.');
- 73 end; { if begin }
- 74
- 75 until (Error = 0) or (Length( OutFileName ) = 0);
- 76
- 77
- 78 { Copy the input file to the output file }
- 79 if Length( OutFileName ) > 0 then
- 80 begin
- 81
- 82 while not Eof(InFile) do
- 83 begin
- 84 Readln( InFile, DataLine );
- 85 Writeln( OutFile, DataLine );
- 86
- 87 { Write a dot on the screen for each line copied }
- 88 Write('.');
- 89 end; { while }
- 90 Writeln;
- 91
- 92 Close( InFile );
- 93 Close( OutFile );
- 94 end; { if begin }
- 95
- 96 end; { if begin }
- 97
- 98 end. { program }
-
- Important Note: Other Text File Features
- Additional text file procedures and facilities are provided in Turbo
- Pascal. The Append procedure operates like Reset, to open an existing file,
- but automatically positions the file pointer to the end of the file so that the
- next Write operation will be made to the end of the file. Normally, text file
- I/O is performed through a 128-byte sized internal file buffer maintained by
- Turbo Pascal. For faster performance, this default buffer may be replaced
- with a larger buffer using the SetTextBuf procedure. Normally, the buffer is
- only output to the disk when it becomes full, but programs can force the buffer
- to be emptied to disk by calling the Flush procedure. These routines are
- briefly described below in the section Other File Operations, and described in
- detail in the library reference section.
-
-
- Sequential Access Data Files
- A frequent use of file operations is reading and writing record-oriented
- data. In this form, the entire contents of a record structure, including all
- of its fields, are written to the disk file. Data values within the record,
- such as integer or real data types, are stored on the disk file in their
- internal format. Listing 3.13 illustrates by creating a small array of a
- TDataRecord, containing name, phone number and age values. The contents of
- each record are written directly to the data file with the statement,
-
- for I := 0 to MaxRecords do
- Write( SeqFile, DataRecords[I] );
-
- After each record is written, the internal file pointer advances to the next
- position in the file. In this example program, the data file is then closed
- and reopened for reading, using Reset. Entire records are then read from the
- file using,
-
- Read ( SeqFile, SampleRecord );
-
- Each record is written back, in sequence. Hence, this particular data file is
- accessed as a sequential data file. Turbo Pascal also provides random access
- data files, permitting reading and writing of specific records anywhere within
- the file.
-
- Listing 3.13. An example program that writes and then reads data to and from a
- sequential file.
- 1 { SEQFILE.PAS }
- 2 program SeqFiles;
- 3 { Demonstrates writing data to a sequential record file
- 4 and reading it back in }
- 5
- 6 const
- 7 MaxRecords = 4;
- 8
- 9 type
- 10 TDataRecord = record
- 11 Name : String[20];
- 12 PhoneNumber : String[14];
- 13 Age : Integer;
- 14 end;
- 15
- 16 const
- 17 DataRecords : Array[0..MaxRecords] of TDataRecord
- 18
- 19 = ( (Name : 'George'; PhoneNumber : '262-1234'; Age : 10 ),
- 20 (Name : 'John' ; PhoneNumber : '262-1235'; Age : 20 ),
- 21 (Name : 'Lisa' ; PhoneNumber : '262-1236'; Age : 22 ),
- 22 (Name : 'Marcia'; PhoneNumber : '262-1237'; Age : 30 ),
- 23 (Name : 'Gwen' ; PhoneNumber : '262-1238'; Age : 4 )
- );
- 24
- 25
- 26 var
- 27 I : Integer;
- 28 SeqFile : File of TDataRecord;
- 29 SampleRecord: TDataRecord;
- 30
- 31 begin
- 32 Assign( SeqFile, 'SEQFILE.DAT');
- 33 Rewrite( SeqFile );
- 34
- 35 for I := 0 to MaxRecords do
- 36 Write( SeqFile, DataRecords[I] );
- 37
- 38 Close ( SeqFile );
- 39
- 40 Reset( SeqFile );
- 41 For I := 0 to MaxRecords do
- 42 begin
- 43 Read( SeqFile, SampleRecord );
- 44 with SampleRecord do
- 45 Writeln('Name=', Name,', Phone #=', PhoneNumber, ', Age=', Age);
- 46 end;
- 47
- 48 Close ( SeqFile );
- 49
- 50 Write('Press Enter when done.');
- 51 Readln;
- 52
- 53
- 54 end. { program }
-
-
- Random Access Data Files
- Program RandFile, in listing 3.14 demonstrates the use of random access
- data files to read and write any record within the data file. The process is
- nearly the same as a sequential data file except that a new procedure, Seek, is
- used to position the internal file pointer to specific records in the file.
- Seek has two parameters: the file identifier and the record number (each data
- record within the file counts as a single record). A statement such as,
-
- Seek ( RandomFile, 10 );
-
- positions the internal file pointer to the 10th record in the data file. The
- next read (or write) will occur at this location in the file.
-
-
- Listing 3.14. How to use random access file operations.
- 1 program RandFile; {RANDFILE.PAS}
- 2 { Demonstrates random access to a record file }
- 3
- 4 const
- 5 MaxRecords = 100;
- 6
- 7 type
- 8 TDataRecord = record
- 9 Name : String[20];
- 10 PhoneNumber : String[14];
- 11 Age : Integer;
- 12 Available : Boolean;
- 13 end;
- 14
- 15 var
- 16 Command : Char;
- 17 RandomFile : File of TDataRecord;
- 18
- 19
- 20
- 21 procedure AddRecord;
- 22 var
- 23 DataRecord : TDataRecord;
- 24 NewName : String[20];
- 25 NewPhone: String[14];
- 26 NewAge : String[20];
- 27 RecordNum : Word;
- 28
- 29
- 30 function FindFreeRecord : Integer;
- 31 { Scans through the file until finding a free or unused record.
- 32 Returns: The record number of the free record, or if no free
- 33 records are found, then returns MaxRecords + 1.
- 34 }
- 35 var
- 36 DataRecord : TDataRecord;
- 37 RecNum : Integer;
- 38 begin
- 39 RecNum := 0;
- 40 repeat
- 41 Seek( RandomFile, RecNum );
- 42 Read( RandomFile, DataRecord );
- 43 if not DataRecord.Available then
- 44 RecNum := RecNum + 1;
- 45 until (RecNum > MaxRecords) Or (DataRecord.Available);
- 46 FindFreeRecord := RecNum;
- 47 end; { FindFreeRecord }
- 48
- 49
- 50 begin { AddRecord }
- 51
- 52 RecordNum := FindFreeRecord;
- 53 if RecordNum > MaxRecords then
- 54 Writeln('The maximum number of records (',MaxRecords,') are in use.')
- 55 else
- 56 begin
- 57
- 58 with DataRecord do
- 59 begin
- 60 Writeln('Adding record #', RecordNum );
- 61 Write('Enter Name ?');
- 62 Readln( Name );
- 63 Write('Enter # PhoneNumber ?');
- 64 Readln( PhoneNumber );
- 65 Write('Enter Age ?');
- 66 Readln( Age );
- 67 Available := False;
- 68 end;
- 69
- 70 Seek( Randomfile, RecordNum );
- 71 Write( RandomFile, DataRecord );
- 72 end;
- 73
- 74 end; { AddRecord }
- 75
- 76
- 77 procedure DisplayRecords;
- 78 var
- 79 DataRecord : TDataRecord;
- 80 I : Integer;
- 81 begin
- 82 for I := 0 to MaxRecords do
- 83 begin
- 84 Seek( Randomfile, I );
- 85 Read( RandomFile, DataRecord );
- 86 if not DataRecord.Available then
- 87 { Found a record that is in use }
- 88 begin
- 89 Writeln('Record #', I);
- 90 with DataRecord do
- 91 Writeln('Name=', Name,', Phone #=', PhoneNumber,', Age=', Age:3);
- 92 Writeln;
- 93 end; { if begin }
- 94 end; { for begin }
- 95 end; { DisplayRecords }
- 96
- 97
- 98 procedure EditRecord;
- 99 var
- 100 DataRecord : TDataRecord;
- 101 Error : Integer;
- 102 NewName : String[20];
- 103 NewPhone: String[14];
- 104 NewAge : String[20];
- 105 RecordNum : Word;
- 106 begin
- 107
- 108 Repeat
- 109
- 110 Write('Enter number of record to edit: ');
- 111 Readln( RecordNum );
- 112
- 113 Seek( RandomFile, RecordNum );
- 114 Read( RandomFile, DataRecord);
- 115 if DataRecord.Available then
- 116 writeln('Record #', RecordNum, ' does not contain any data.');
- 117
- 118 Until not DataRecord.Available;
- 119
- 120
- 121 with DataRecord do
- 122 begin
- 123 Write('Name =', Name,'(CR=no change) ? ');
- 124 Readln( NewName );
- 125 if NewName <> '' then
- 126 Name := NewName;
- 127 Write('PhoneNumber =', PhoneNumber, '(CR=no change) ? ');
- 128 Readln( NewPhone );
- 129 if NewPhone <> '' then
- 130 PhoneNumber := NewPhone;
- 131 Write('Age =', Age, '(CR=no change) ? ');
- 132 Readln( NewAge );
- 133 if NewAge <> '' then
- 134 Val( NewAge, Age, Error);
- 135 end;
- 136 Seek( RandomFile, RecordNum );
- 137 Write( RandomFile, DataRecord );
- 138 end; { EditRecord }
- 139
- 140
- 141 procedure OpenFile;
- 142 var
- 143 SampleRecord : TDataRecord;
- 144 Error : Integer;
- 145 I : Integer;
- 146 begin
- 147 { Open existing file or create a new random access data file }
- 148 Assign( RandomFile, 'RANDFILE.DAT');
- 149 {$I-}
- 150 Reset( RandomFile );
- 151 {$I+}
- 152 Error := IoResult;
- 153 if Error <> 0 then
- 154 begin
- 155 { Create and initialize a new file. Set all records to available }
- 156 Rewrite( RandomFile );
- 157 SampleRecord.Available := True;
- 158 for I := 0 to MaxRecords do
- 159 write( RandomFile, SampleRecord );
- 160 end; { if begin }
- 161 end; { OpenFile }
- 162
- 163
- 164 begin { RandFile }
- 165
- 166 OpenFile;
- 167
- 168 repeat
- 169 Write('A)dd record, D)isplay records, E)dit record, Q)uit? ');
- 170 Readln( Command );
- 171 Command := Upcase( Command );
- 172 case Command of
- 173 'A' : AddRecord;
- 174 'D' : DisplayRecords;
- 175 'E' : EditRecord;
- 176 end; { case }
- 177 until Command = 'Q';
- 178
- 179 Close( RandomFile );
- 180
- 181
- 182 Write('Press Enter when done.');
- 183 Readln;
- 184
- 185
- 186 end. { program }
-
- The actual data record is defined in TDataRecord, containing 4 fields:
- Name, PhoneNumber, Age, and a Boolean flag Available. The Available flag is
- used to keep track of which records are in use and which have yet to be used.
- Procedure OpenFile first tries to open an existing 'RANDFILE.DAT', since
- if the file already exists, it will then be used as-is. However, if no such
- file exists, a new one is created by calling Rewrite. For each of the records
- in file (the total number of records is specified in the MaxRecords constant),
- the Available flag is set to True, using this code:
-
- SampleRecord.Available := True;
- for I := 0 to MaxRecords do
- write( RandomFile, SampleRecord );
-
- Note that we don't care about the contents of the other fields. As long as the
- Available flag is set to True, we know that the record is available for writing
- new data to, and we will ignore the contents of the other fields.
- In the main body of the program, a repeat-until loop is used to prompt for
- a command, A)dd, D)isplay, E)dit or Q)uit the program (this notation is used to
- suggest that you should only enter the first letter of each command). After
- converting to upper case, the program uses a case statement to determine which
- procedure should execute.
- AddRecord calls its local function FindFreeRecord to find the next free
- record (one with Available = True). FindFreeRecord merely reads through the
- file, one record at a time, until either finding a free record, or reaching the
- end of the data file. Back inside AddRecord, the user is prompted for a new
- name, phone number and age values; the Available flag is set to False and the
- record is written out to the file. Note the use of Seek to position to the
- free record in the file, and then a Write procedure to output the record data
- to the file.
- The EditRecord procedure takes a record number as input, seeks to the
- given record, reads the data from the file, and gives you a chance to make
- changes. The altered data is then output to the file.
- DisplayRecords scans through the file, displaying the record number, name,
- phone number and age values for each record that is in use.
- For practice, you may wish to modify this program to include a Delete
- function. All that's needed is to output a new record with the Available flag
- set to True, for each record that is deleted.
-
- Important note: Writing Pointer values to disk files
- When writing a record structure to a disk file, any pointer type values
- contained in the record are also written to the file. However, when these
- values are read back into memory from a disk file, their value is meaningless.
- Pointers to internal memory addresses are only valid when used within the
- original execution of the program.
- Instead of storing pointers in the disk file, you must be able to recreate
- the internal data structure without referencing the pointer values. A simple
- approach is to output the data records in the exact order that they will be
- read back. Upon reading each record from the file, you must recreate the
- internal data strcuture, via calls to New to allocate new data records from the
- heap, and then explicitly reassign any pointer values to the new allocations.
- More complicated structures may require that you create a file record
- number field, and instead of using pointer values in the data file, store
- actual file record numbers. Upon reading the file, you would then use New to
- create a new internal record, and copy the values read from disk into the
- record, setting pointers as appropriate, to point to other records in the
- internal memory structure.
-
-
- BlockRead and BlockWrite: The Use of Untyped Files
- In addition to reading and writing specific data types, Turbo Pascal
- provides for untyped data files, using just the File keyword, and two
- procedures BlockRead and BlockWrite, for reading and writing data to such a
- file. By default, each untyped files is treated as having 128 bytes per block
- (but can be set to other values). This means that data is read or written in
- 128-byte sized chuncks called blocks.
- BlockRead and BlockWrite are especially useful for performing high speed
- file copy operations because of their ability to read and write very large
- blocks of data in a single statement. Block I/O is also used by programs that
- perform their own internal data formatting. For example, a word processor may
- store its internal representation of a document directly to disk using
- BlockWrite to output the document's internal memory structure. Data base and
- spreadsheet applications may also build buffers of data for faster reading and
- writing of data base and spreadsheet files.
- An untyped file is declared using the File keyword by itself, as in this
- declaration of InFile and OutFile:
-
- var
- InFile, OutFile : File;
-
- BlockRead has 3 or 4 parameters, depending on its mode of operation. The same
- is true of BlockWrite. At a minimum, each procedure has 3 parameters:
-
- BlockRead( FileId, Buffer, NumBlocks );
- BlockWrite( FileId, Buffer, NumBlocks );
-
- where,
-
- FileId is a file identifier specifying the file where the operation will
- be performed,
-
- Buffer, is typically an array of char or an array of byte large enough
- to hold all the data,
-
- NumBlocks is the number of blocks to read into the buffer, where each
- block is either the default of 128 bytes, or is a different block size
- as specified with the Reset or Rewrite procedures (see below).
-
- An optional 4th parameter returns the number of blocks actually read,
- which, in the event that something prevented the program from reading
- the number of blocks that were requested, may be different than the
- number of blocks requested. For example, a program might request 4
- blocks but only read 3 blocks before reaching the end of the file. In
- this case, the 4th parameter returns a value of 3.
- An example, given the definition of Buffer as:
-
- var
- Buffer : Array [0..2047] of Char;
-
- then, the statement,
-
- BlockRead ( FileId, Buffer, 16 );
-
- reads sixteen 128 byte-sized blocks from the file and places them in Buffer.
-
-
- Specifying Different Block Sizes
- The Reset and Rewrite procedures have an optional 2nd parameter to specify
- a different block size. For example,
-
- Reset ( FileId, 1024 );
-
- specifies that each block of data read from the untyped FileId will contain
- 1024 bytes of data. In this instance, you may write,
-
- BlockRead ( FileId, Buffer, 2 );
-
- and read two 1,204 byte blocks from the disk file.
- A problem with BlockRead is that it cannot read data that is less than the
- block size. For instance, what happens if you attempt to read a 1,204 byte
- sized block from a file having only 300 bytes? If you use BlockRead with the
- optional 4th parameter, as for instance,
-
- BlockRead ( FileId, Buffer, 1, Result );
-
- then Result will be 0, indicating that the amount of data you requested could
- not be read. The partial record is stored in Buffer, but you have no way of
- knowing how many bytes were actually read.
- The solution to this problem is to open the file with a block size of 1
- byte, and set the NumBlocks parameter to the Buffer size. For example,
-
- Reset ( FileId, 1 );
- BlockRead ( FileId, Buffer, SizeOf(Buffer), Result );
-
- Now, if the amount of data to read is less than 2048 bytes, the actual number
- read is returned in Result. Listing 3.15 is a procedure CopyFile that copies
- one file to another, using a blocksize of 1, and buffer size of 1,204 bytes
- (see the declaration of TFileBuffer). For faster performance you can change
- the declaration of TFileBuffer to a much larger size, such as 32,768 bytes.
- As with other file operations, use the {$I-} compiler option to disable
- automatic I/O result checking. Write your own error checking routines to check
- the contents of IOResult to determine success or failure of block operations.
-
-
- Listing 3.15. Demonstration of the BlockRead and BlockWrite functions for fast
- file copying.
- 1 function CopyAFile ( Source, Dest : String ) : Integer;
- 2 {COPYFILE.PAS}
- 3 { Purpose:
- 4 Copies the filenamed in 'Source' to the file named in 'Dest'.
- 5
- 6 Returns:
- 7 0 = copy was okay
- 8 1 = not enough RAM memory to copy the file
- 9 2 = error occurred when writing to the 'Dest' file
- 10 3 = Could not open the source file
- 11 4 = Could not open the destination file
- 12 }
- 13 label
- 14 ExitProc;
- 15
- 16 type
- 17 TFileBuffer = Array [0..1023] of Byte;
- 18 { Copies the file in 1k chunks. For a larger buffer,
- 19 increase the size of the byte array. }
- 20 var
- 21 BytesIn : Integer; { Number of bytes read in }
- 22 BytesOut : Integer; { Number of bytes written out }
- 23 F1 : File; { F1=file to read, F2=file to write }
- 24 F2 : File;
- 25 FileBuffer : ^TFileBuffer;
- 26 Dialog : PDialog;
- 27 Bounds : TRect;
- 28
- 29 begin { CopyFile }
- 30
- 31 New( FileBuffer );
- 32 if FileBuffer = NIL then
- 33 CopyAFile := 1 {Not enough RAM memory to do a copy}
- 34 else
- 35 begin
- 36
- 37 { Open the source file }
- 38 Assign ( F1, Source );
- 39 {$I-}
- 40 Reset ( F1, 1 );
- 41 if IoResult <> 0 then
- 42 begin
- 43 CopyAFile := 3; {Error on opening source file}
- 44 goto ExitProc;
- 45 end;
- 46
- 47 { Open the destination file }
- 48 Assign ( F2, Dest );
- 49 Rewrite ( F2, 1 );
- 50 if IoResult <> 0 then
- 51 begin
- 52 CopyAFile := 4; {Error on opening the destination file}
- 53 goto ExitProc;
- 54 end; { if }
- 55
- 56 repeat
- 57 BlockRead ( F1, FileBuffer^, SizeOf(FileBuffer^), BytesIn );
- 58 if BytesIn > 0 then
- 59 begin
- 60 { Since we read something, go ahead and write it to the
- destination }
- 61 BlockWrite ( F2, FileBuffer^, BytesIn, BytesOut );
- 62 if BytesIn <> BytesOut then
- 63 begin
- 64 CopyAFile := 2; {Error occurred while writing the output}
- 65 {$I-}
- 66 Close ( F2 );
- 67 Erase ( F2 );
- 68 Close ( F1 );
- 69 {$I+}
- 70 goto ExitProc;
- 71 end; { begin }
- 72 end; { if }
- 73 until BytesIn = 0;
- 74
- 75 CopyAFile := 0;
- 76 Close ( F1 );
- 77 Close ( F2 );
- 78
- 79 end; { begin }
- 80
- 81 ExitProc:
- 82
- 83 if FileBuffer <> NIL then
- 84 Dispose (FileBuffer);
- 85
- 86 end; { CopyAFile }
- 87
-
- Important Note: Maximum buffer size and maximum data to read or write
- The maximum amount of data that can be read with BlockRead or written with
- BlockWrite is limited in the following ways:
- Individual data structures in Turbo Pascal can be no larger than 65,521
- bytes.
- The file record size times the count of bytes to read or write, must be
- 65,535 (or less) since its stored in a Word data type. In other words,
- SizeOf(Buffer) * NumBlocks must be less than or equal to 65,535.
-
-
- Other File Operations
- In addition to the basic file operation facilities covered in the previous
- sections, Turbo Pascal provides a variety of standard procedures for creating
- directories, switching to other directories, erasing and renaming files and so
- on. Other functions and variables provide additional features. The following
- is a summary of the available functions; they are described in detail in the
- library reference section.
-
-
- Procedures
-
- ChDir ( S: String ): Changes the current directory to the path
- specified by S.
-
- Erase ( var F): Erases or deletes the file associated with the closed
- file identifier F (with the name previously given to it by Assign),
-
- GetDir (D: Byte; var S: String): Where D=1 for drive A, 2 for drive B,
- etc, or 0 for the current drive, GetDir returns the current directory
- name in variable S.
-
- MkDir( S: String ): Used to create new subdirectories, where S is the
- path, including the subdirectory name, to create.
-
- Rename( var F; Newname : String ): Where F is a closed file identifier
- having a name set with the Assign procedure, Rename changes the name of
- that file to the name specified by Newname.
-
- RmDir( S : String ): Deletes an empty subdirectory specified by S.
-
- Truncate( var F ): The current file position in open file F becomes the
- new end of file, effectively disgarding any records that may follow the
- current record.
-
-
- Functions
-
- FilePos (var F): Longint: Returns the current position in the non-text
- file as the record number of the file pointer.
-
- FileSize (var F): Longint : Where F is an open non-text file, this
- returns the size of the file, in number of components. If F is a file
- of Char, then FileSize(F) returns the size in bytes. If F is a file of
- Integer, then FileSize(F) returns the number of integer records in the
- file.
-
-
- Text file procedures
-
- Append (var F: Text): Like Reset, for opening an existing text file, but
- automatically positions the current file position to the end of the file
- so that the next output will be written at the end of the current file.
-
- Flush( var F: Text ): Empties the internal buffer associated with text
- file F. to the disk file.
-
- SetTextBuf(var F: Text; var Buf [; Size : Word ] ): By default, all
- text files use an internal 128 byte-sized buffer. For faster text file
- performance, programs can establish their own text file buffer by
- calling SetTextBuf and passing to it their own data block to be used for
- the buffer. SizeOf(Buf) becomes the new buffer size, or a different
- size may be explicitly provided with the optional Size parameter. Calls
- to SetTextBuf should occur just prior to Append, Reset or Rewrite.
-
- Eoln ( var F : Text ): Returns True if the next character is the text
- file is an end of line character (e.g. carriage return).
-
- SeekEof( var F: Text ): For text file use only, SeekEof is equivalent
- to the Eof function except it skips over any trailing blanks, tabs or
- blank lines.
-
- SeekEoln( var F: Text ): For text file use only, SeekEoln is equivalent
- to Eoln, except that is skips over trailing blanks and tabs at the end
- of a line.
-
-
- Untyped Files
-
- FileMode: By assigning a value to FileMode prior to opening a file with
- Reset, you can specify an access mode for the file. A value of 0
- specifies Read only, 1 specifies Write only, and 2, the default value,
- specifies Read/write access to the file. The value of FileMode remains
- in effect for all subsequent Reset operations, until set to some other
- value.
-
-
-
- Turbo Pascal Memory Limitations
-
- Maximum statement width: 126 characters
-
- Maximum size of generated code per code unit: 64k bytes
- The program module and each Unit may contain up to 64k bytes of code.
- Ifthe program or unit exceeds this value, then you must split it up into
- smaller sections.
-
- Maximum size of global and typed constants: 64k bytes
- If your program must have several large values, such as arrays, as
- global values, and their combined size will exceed this value, then you
- must recode your program to reduce the memory usage. A simple approach
- is to dynamically allocate the arrays and define only a pointer to the
- array as a global value.
-
- Maximum program stack size (used for procedure and function call return
- address and all local variable storage): 64k bytes
- The default stack size is 16k bytes but may be adjusted up or down using
- the $M compiler directive or the IDE's Options/Memory Sizes menu
- selection.
-
- Maximum heap size: 0 to 640k bytes
- The heap's default memory allocation is all the memory left over after
- the code is loaded and the stack and data segments are allocated. The
- heap will take all the available memory up to its maximum declared size,
- which is 640k by default. You will want to set the default value to a
- lower limit especially if your program will be memory resident with
- other software, or if your program launches other applications using the
- Exec procedure.
-
- Maximum data allocation size: 65,521 bytes
- You cannot allocate a single data structure (such as an array) that is
- larger than this size.
-